import { ComponentOptions, h } from "vue";
import { FormItemContentRenderParams, FormItemRenderOptions, VxeGlobalRendererHandles, VxeTableDefines, VxeColumnPropTypes } from "../../../../../types/all";
import XEUtils from "xe-utils";
import { componentMap } from "../componentMap";
import { ComponentType } from "../componentType";
import { createPlaceholderMessage } from "../helper";
import { dayjs } from "element-plus";

/**
 * @description: 获取组件
 */
export function getComponent(componentName: ComponentType) {
    const Component = componentMap.get(componentName as ComponentType);
    if (!Component) throw `您还没注册此组件 ${componentName}`;
    return Component as ComponentOptions;
}

export function isEmptyValue(cellValue: any) {
    return cellValue === null || cellValue === undefined || cellValue === "";
}

export function formatText(cellValue: any) {
    return "" + (isEmptyValue(cellValue) ? "" : cellValue);
}

export function cellText(cellValue: any): string[] {
    return [formatText(cellValue)];
}

/**
 * @description: 方法名转换
 */
export function getOnName(type: string) {
    return "on" + type.substring(0, 1).toLocaleUpperCase() + type.substring(1);
}

export function toDayStringDate(value: any, format: string) {
    return dayjs(value, format).date;
}

export function toDayDateString(date: any, format: string) {
    return dayjs(date).format(format);
}

export function parseDate(value: any, props: { [key: string]: any }) {
    return value && props.valueFormat ? toDayStringDate(value, props.valueFormat) : value;
}

export function getFormatDate(value: any, props: { [key: string]: any }, defaultFormat: string) {
    return value ? toDayDateString(parseDate(value, props), props.format || defaultFormat) : value;
}

export function getFormatDates(values: any[], props: { [key: string]: any }, separator: string, defaultFormat: string) {
    return XEUtils.map(values, (date: any) => getFormatDate(date, props, defaultFormat)).join(separator);
}

export function equalDaterange(cellValue: any, data: any, props: { [key: string]: any }, defaultFormat: string) {
    cellValue = getFormatDate(cellValue, props, defaultFormat);
    return cellValue >= getFormatDate(data[0], props, defaultFormat) && cellValue <= getFormatDate(data[1], props, defaultFormat);
}

export function getCellLabelVNs(renderOpts: VxeColumnPropTypes.EditRender, params: VxeGlobalRendererHandles.RenderCellParams, cellLabel: any) {
    const { placeholder } = renderOpts;
    return [
        h(
            "span",
            {
                class: "vxe-cell--label",
            },
            placeholder && isEmptyValue(cellLabel)
                ? [
                      h(
                          "span",
                          {
                              class: "vxe-cell--placeholder",
                          },
                          formatText(vxetable._t(placeholder))
                      ),
                  ]
                : formatText(cellLabel)
        ),
    ];
}

export function getCellEditFilterProps(renderOpts: VxeGlobalRendererHandles.RenderOptions, params: VxeGlobalRendererHandles.RenderEditParams | VxeGlobalRendererHandles.RenderFilterParams, value: any, defaultProps?: { [prop: string]: any }) {
    return XEUtils.assign({}, defaultProps, renderOpts.props, { [getModelProp(renderOpts)]: value });
}

export function getFilterOns(renderOpts: VxeGlobalRendererHandles.RenderOptions, params: VxeGlobalRendererHandles.RenderFilterParams, option: VxeTableDefines.FilterOption, changeFunc: Function) {
    return createEvents(
        renderOpts,
        params,
        (value: any) => {
            // 处理 model 值双向绑定
            option.data = value;
        },
        changeFunc
    );
}

/**
 * @description: 获取组件传值所接受的属性
 */
export function getModelProp(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
    return "modelValue";
}

/**
 * @description: 回去双向更新的方法
 */

function getModelEvent(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
    return "update:modelValue";
}

/**
 * @description: chang值改变方法
 * @param {}
 * @return {*}
 * @author: *
 */
function getChangeEvent(renderOpts: VxeGlobalRendererHandles.RenderOptions) {
    let type = "change";
    switch (renderOpts.name) {
        case "ElAutocomplete":
            type = "select";
            break;
        case "ElInput":
        case "ElInputNumber":
            type = "input";
            break;
    }
    return type;
}

function getClickEvent() {
    return "click";
}
/**
 * @description: 获取方法
 * @param {}
 * @return {*}
 * @author: *
 */
export function createEvents(renderOpts: VxeGlobalRendererHandles.RenderOptions, params: VxeGlobalRendererHandles.RenderParams, inputFunc?: Function, changeFunc?: Function, clickFunc?: Function) {
    const { events } = renderOpts;
    const modelEvent = getModelEvent(renderOpts);
    const changeEvent = getChangeEvent(renderOpts);
    const clickEvent = getClickEvent();
    const isSameEvent = changeEvent === modelEvent;
    const ons: { [type: string]: Function } = {};

    XEUtils.objectEach(events, (func: Function, key: string) => {
        ons[getOnName(key)] = function (...args: any[]) {
            func(params, ...args);
        };
    });
    if (inputFunc) {
        ons[getOnName(modelEvent)] = function (targetEvnt: any) {
            inputFunc(targetEvnt);
            if (events && events[modelEvent]) {
                events[modelEvent](params, targetEvnt);
            }
            if (isSameEvent && changeFunc) {
                changeFunc(targetEvnt);
            }
        };
    }
    if (!isSameEvent && changeFunc) {
        ons[getOnName(changeEvent)] = function (...args: any[]) {
            changeFunc(...args);
            if (events && events[changeEvent]) {
                events[changeEvent](params, ...args);
            }
        };
    }
    if (clickFunc) {
        ons[getOnName(clickEvent)] = function (...args: any[]) {
            clickFunc(...args);
            if (events && events[clickEvent]) {
                events[clickEvent](params, ...args);
            }
        };
    }
    return ons;
}

export function getItemOns(renderOpts: VxeGlobalRendererHandles.RenderOptions, params: FormItemContentRenderParams) {
    const { $form, data, field } = params;
    return createEvents(
        renderOpts,
        params,
        (value: any) => {
            // 处理 model 值双向绑定
            XEUtils.set(data, field, value);
        },
        () => {
            // 处理 change 事件相关逻辑
            $form.updateStatus(params);
        }
    );
}

export function getEditOns(renderOpts: VxeGlobalRendererHandles.RenderOptions, params: VxeGlobalRendererHandles.RenderEditParams) {
    const { $table, row, column } = params;
    return createEvents(
        renderOpts,
        params,
        (value: any) => {
            // 处理 model 值双向绑定
            XEUtils.set(row, column.field, value);
        },
        () => {
            // 处理 change 事件相关逻辑
            $table.updateStatus(params);
        }
    );
}

/**
 * @description: 获取属性
 */
export function createProps(renderOpts: VxeGlobalRendererHandles.RenderOptions, value: any, defaultProps?: { [prop: string]: any }) {
    const name = renderOpts.name as ComponentType;
    return XEUtils.assign(
        {
            placeholder: createPlaceholderMessage(name),
            allowClear: true,
        },
        defaultProps,
        renderOpts.props,
        {
            [getModelProp(renderOpts)]: value,
        }
    );
}

/**
 * @description: 创建单元格默认显示内容
 */
export function createDefaultRender(defaultProps?: { [key: string]: any }, callBack?: (renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions, params: VxeGlobalRendererHandles.RenderDefaultParams) => Record<string, any>) {
    return function (renderOpts: VxeGlobalRendererHandles.RenderDefaultOptions, params: VxeGlobalRendererHandles.RenderDefaultParams) {
        const { row, column, $table } = params;
        const { name, attrs }: any = renderOpts;
        const cellValue = XEUtils.get(row, column.field as string);
        const args = (callBack && callBack(renderOpts, params)) ?? {};

        const Component = getComponent(name);
        return [
            h(Component, {
                ...attrs,
                ...createProps(renderOpts, cellValue, defaultProps),
                ...args,
                ...createEvents(
                    renderOpts,
                    params
                    // (value: any) => XEUtils.set(row, column.field as string, value),
                    // () => $table.updateStatus(params)
                ),
            }),
        ];
    };
}

/**
 * @description: 创建编辑单元格
 */
export function createEditRender(defaultProps?: { [key: string]: any }, callBack?: (renderOpts: VxeGlobalRendererHandles.RenderEditOptions, params: VxeGlobalRendererHandles.RenderEditParams) => Record<string, any>) {
    return function (renderOpts: VxeGlobalRendererHandles.RenderEditOptions, params: VxeGlobalRendererHandles.RenderEditParams) {
        const { row, column, $table } = params;
        const { name, attrs }: any = renderOpts;
        const cellValue = XEUtils.get(row, column.field as string);
        const args = (callBack && callBack(renderOpts, params)) ?? {};

        const Component = getComponent(name);
        return [
            h(Component, {
                ...attrs,
                ...createProps(renderOpts, cellValue, defaultProps),
                ...args,
                ...createEvents(
                    renderOpts,
                    params,
                    (value: any) => {
                        XEUtils.set(row, column.field as string, value);
                    },
                    (value: any) => {
                        $table.updateStatus(value);
                        XEUtils.set(row, column.field as string, value);
                    }
                ),
            }),
        ];
    };
}
/**
 * @description: 创建时间编辑单元格
 */
export function createEditDateRender(defaultProps?: { [key: string]: any }, callBack?: (renderOpts: VxeGlobalRendererHandles.RenderEditOptions, params: VxeGlobalRendererHandles.RenderEditParams) => Record<string, any>, callBackFormat?: (renderOpts: VxeGlobalRendererHandles.RenderCellOptions, params: VxeGlobalRendererHandles.RenderCellParams) => Object) {
    return function (renderOpts: VxeGlobalRendererHandles.RenderEditOptions, params: VxeGlobalRendererHandles.RenderEditParams) {
        const { row, column, $table } = params;
        const { name, attrs }: any = renderOpts;
        const cellValue = XEUtils.get(row, column.field as string);
        const args = (callBack && callBack(renderOpts, params)) ?? {};
        const defaultFormat = (callBackFormat && callBackFormat(renderOpts, params)) ?? {};

        const Component = getComponent(name);
        return [
            h(Component, {
                ...attrs,
                ...createProps(renderOpts, cellValue, defaultProps),
                ...args,
                ...createEvents(
                    renderOpts,
                    params,
                    () => {},
                    (value: any) => {
                        console.log("创建时间编辑单元格", value);
                        if (value) {
                            XEUtils.set(row, column.field as string, dayjs(value).format(defaultFormat["format"]));
                        } else {
                            XEUtils.set(row, column.field as string, null);
                        }
                    },
                    () => {
                        $table.updateStatus(params);
                    }
                ),
            }),
        ];
    };
}

/**
 * @description: 创建筛选渲染内容
 */
export function createFilterRender(defaultProps?: { [key: string]: any }, callBack?: (renderOpts: VxeGlobalRendererHandles.RenderFilterOptions, params: VxeGlobalRendererHandles.RenderFilterParams) => Record<string, any>) {
    return function (renderOpts: VxeGlobalRendererHandles.RenderFilterOptions, params: VxeGlobalRendererHandles.RenderFilterParams) {
        const { column } = params;
        const { name, attrs }: any = renderOpts;
        const args = (callBack && callBack(renderOpts, params)) ?? {};

        const Component = getComponent(name);
        return [
            h(
                "div",
                {
                    class: "vxe-table--filter-antd-wrapper",
                },
                column.filters.map((option, oIndex) => {
                    const optionValue = option.data;
                    const checked = !!option.data;

                    return h(Component, {
                        key: oIndex,
                        ...attrs,
                        ...createProps(renderOpts, optionValue, defaultProps),
                        ...args,
                        ...createEvents(
                            renderOpts,
                            params,
                            (value: any) => {
                                // 处理 model 值双向绑定
                                option.data = value;
                            },
                            () => {
                                // 处理 change 事件相关逻辑
                                const { $panel } = params;
                                $panel.changeOption(null, checked, option);
                            }
                        ),
                    });
                })
            ),
        ];
    };
}

export function handleConfirmFilter(params: VxeGlobalRendererHandles.RenderFilterParams, checked: boolean, option: VxeTableDefines.FilterOption) {
    const { $panel } = params;
    $panel.changeOption(null, checked, option);
}

/**
 * @description: 默认过滤
 * @param {}
 * @return {*}
 * @author: *
 */

export function createDefaultFilterRender() {
    return function (params: VxeGlobalRendererHandles.FilterMethodParams) {
        const { option, row, column } = params;
        const { data } = option;
        const cellValue = XEUtils.get(row, column.field as string);
        return cellValue === data;
    };
}

/**
 * @description: 创建 form表单渲染
 */
export function createFormItemRender(defaultProps?: { [key: string]: any }, callBack?: (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) => Record<string, any>) {
    return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
        const args = (callBack && callBack(renderOpts, params)) ?? {};
        const { data, property, $form } = params;
        const { name }: any = renderOpts;
        const { attrs } = renderOpts;
        const itemValue = XEUtils.get(data, property);
        const Component = getComponent(name);
        return [
            h(Component, {
                ...attrs,
                ...createProps(renderOpts, itemValue, defaultProps),
                ...args,
                ...createEvents(
                    renderOpts,
                    params,
                    (value: any) => {
                        console.log("值改变", value);
                        // 处理 model 值双向绑定
                        XEUtils.set(data, property, value);
                    },
                    () => {
                        console.log("change事件");
                        // 处理 change 事件相关逻辑
                        $form.updateStatus({
                            ...params,
                            field: property,
                        });
                    }
                ),
            }),
        ];
    };
}

// 表单重置
export function createitemResetMethodRender({ $form, data, field, item }: any) {
    data[field] = null;
    $form.updateStatus(item, null);
}

/**
 * @description: cell渲染
 */
export function createCellRender(getSelectCellValue: Function, callBack?: (renderOpts: VxeGlobalRendererHandles.RenderCellOptions, params: VxeGlobalRendererHandles.RenderCellParams) => Array<any>) {
    return function (renderOpts: VxeGlobalRendererHandles.RenderCellOptions, params: VxeGlobalRendererHandles.RenderCellParams) {
        const args = (callBack && callBack(renderOpts, params)) ?? [];
        const cellLabel = getSelectCellValue && getSelectCellValue(renderOpts, params, ...args);
        const { placeholder } = renderOpts;

        return [
            h(
                "span",
                {
                    class: "vxe-cell--label",
                },
                placeholder && isEmptyValue(cellLabel)
                    ? [
                          h(
                              "span",
                              {
                                  class: "vxe-cell--placeholder",
                              },
                              formatText(placeholder)
                          ),
                      ]
                    : formatText(cellLabel)
            ),
        ];
    };
}

/**
 * @description: 创建 导出渲染
 * @param {}
 * @return {*}
 * @author: *
 */
export function createExportMethod(getExportCellValue: Function, callBack?: (params: VxeGlobalRendererHandles.ExportMethodParams) => Array<any>) {
    return function (params: VxeGlobalRendererHandles.ExportMethodParams) {
        const { row, column, options } = params;
        const args = (callBack && callBack(params)) ?? [];
        return options && options.original ? XEUtils.get(row, column.field as string) : getExportCellValue(column.editRender || column.cellRender, params, ...args);
    };
}

/**
 * @description: 创建单元格默认显示内容
 */
export function createToolbarToolRender(defaultProps?: { [key: string]: any }, callBack?: (renderOpts: VxeGlobalRendererHandles.RenderToolOptions, params: VxeGlobalRendererHandles.RenderToolParams) => Record<string, any>) {
    return function (renderOpts: VxeGlobalRendererHandles.RenderToolOptions, params: VxeGlobalRendererHandles.RenderToolParams) {
        const { name, attrs }: any = renderOpts;
        const args = (callBack && callBack(renderOpts, params)) ?? {};

        const Component = getComponent(name);
        return [
            h(Component, {
                ...attrs,
                ...createProps(renderOpts, null, defaultProps),
                ...args,
                ...createEvents(renderOpts, params),
            }),
        ];
    };
}

/**
 * @description: 创建Radio内容
 */
export function createFormItemRadioRender(defaultProps?: { [key: string]: any }, callBack?: (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) => Record<string, any>) {
    return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
        const { name, options = [], optionProps = {}, attrs }: any = renderOpts;
        const labelProp = optionProps.label || "label";
        const valueProp = optionProps.value || "value";
        const args = (callBack && callBack(renderOpts, params)) ?? {};
        const { data, property } = params;
        const itemValue = XEUtils.get(data, property);

        const Component = getComponent(name);
        return [
            h(
                Component,
                {
                    ...args,
                    ...attrs,
                    ...createProps(renderOpts, itemValue, defaultProps),
                    ...getItemOns(renderOpts, params),
                },
                {
                    default: () => {
                        return options.map((option: any, oIndex: any) => {
                            return h(
                                getComponent("ElRadio"),
                                {
                                    key: oIndex,
                                    label: option[valueProp],
                                    disabled: option.disabled,
                                },
                                {
                                    default: () => cellText(option[labelProp]),
                                }
                            );
                        });
                    },
                }
            ),
        ];
    };
}
/**
 * @description: 创建Checkbox内容
 */
export function createFormItemCheckboxRender(defaultProps?: { [key: string]: any }, callBack?: (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) => Record<string, any>) {
    return function (renderOpts: FormItemRenderOptions, params: FormItemContentRenderParams) {
        const { name, options = [], optionProps = {}, attrs }: any = renderOpts;
        const labelProp = optionProps.label || "label";
        const valueProp = optionProps.value || "value";
        const args = (callBack && callBack(renderOpts, params)) ?? {};
        const { data, property } = params;
        const itemValue = XEUtils.get(data, property);

        const Component = getComponent(name);
        return [
            h(
                Component,
                {
                    ...args,
                    ...attrs,
                    ...createProps(renderOpts, itemValue, defaultProps),
                    ...getItemOns(renderOpts, params),
                },
                {
                    default: () => {
                        return options.map((option: any, oIndex: any) => {
                            return h(
                                getComponent("ElCheckbox"),
                                {
                                    key: oIndex,
                                    label: option[valueProp],
                                    disabled: option.disabled,
                                },
                                {
                                    default: () => cellText(option[labelProp]),
                                }
                            );
                        });
                    },
                }
            ),
        ];
    };
}
